
package com.epam.android.training.app.services;

import com.epam.android.training.app.R;
import com.epam.android.training.app.db.FeedsDb;
import com.epam.android.training.app.db.entities.Feed;
import com.epam.android.training.app.db.entities.FeedItem;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import android.content.Context;
import android.util.Log;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

/**
 * RSS Handler.
 * 
 * @author Natalie
 */
public class RSSHandler extends DefaultHandler {

  private static final String TAG = "RSSHandler";

  private static final String ITEM = "item";

  private static final String TITLE = "title";

  private static final String LINK = "link";

  private static final String PUB_DATE = "pubDate";

  private final Feed currentFeed = new Feed();

  private final FeedItem item = new FeedItem();

  private FeedsDb db = null;

  private final int RSS_TITLE = 1;

  private final int RSS_LINK = 2;

  private final int RSS_PUBDATE = 5;

  private boolean isItem = false;

  private boolean isUpdate;

  private int currentstate = 0;

  private Context context;

  @Override
  public void startElement(String uri, String name, String qname, Attributes atts) {
    if (name.equals(ITEM)) {
      isItem = true;
    }
    if (name.equals(TITLE)) {
      currentstate = RSS_TITLE;
      return;
    }
    if (name.equals(LINK)) {
      currentstate = RSS_LINK;
      return;
    }
    if (name.equals(PUB_DATE)) {
      currentstate = RSS_PUBDATE;
      return;
    }
    currentstate = 0;
  }

  @Override
  public void endElement(String namespaceURI, String name, String qName) throws SAXException {
    if (name.equals("item")) {
      if (isItem && item.getUrl() != null && item.getTitle() != null && item.getDate() != null) {

        SimpleDateFormat sdf = new SimpleDateFormat(context.getString(R.string.date_format));
        Date date = new Date();
        try {
          date = sdf.parse(item.getDate());
          if (!isUpdate) {
            db.insertFeedItem(item.getTitle(), date.getTime(), item.getUrl().toExternalForm());
          } else {
            db.insertIfNotExist(item.getTitle(), date.getTime(), item.getUrl().toExternalForm());
          }
          isItem = false;
        } catch (ParseException e) {
          Log.e(TAG, e.getLocalizedMessage());
        }
      }
    } else {
      currentstate = 0;
      if (!isItem && currentFeed.getUrl() != null && currentFeed.getTitle() != null) {
        // TODO: write to db feed data
      }
    }
  }

  @Override
  public void characters(char ch[], int start, int length) {
    String theString = new String(ch, start, length);
    switch (currentstate) {
      case RSS_TITLE:
        if (isItem) {
          item.setTitle(theString);
        } else {
          currentFeed.setTitle(theString);
        }
        currentstate = 0;
        break;
      case RSS_PUBDATE:
        if (isItem) {
          item.setDate(theString);
        }
        currentstate = 0;
        break;
      case RSS_LINK:
        if (isItem) {
          try {
            item.setUrl(new URL(theString));
          } catch (MalformedURLException e) {
            Log.e(TAG, e.getLocalizedMessage());
          }
        }
        currentstate = 0;
        break;
      default:
        return;
    }
  }

  public Feed createFeed(Context context, URL url, boolean update) {
    db = new FeedsDb(context);
    isUpdate = update;
    currentFeed.setUrl(url);
    this.context = context;
    SAXParserFactory spf = SAXParserFactory.newInstance();
    SAXParser sp;
    try {
      sp = spf.newSAXParser();
      XMLReader xr = sp.getXMLReader();
      xr.setContentHandler(this);
      InputSource source = new InputSource(url.openStream());
      xr.parse(source);

    } catch (IOException e) {
      Log.e(TAG, e.getLocalizedMessage());
    } catch (ParserConfigurationException e) {
      Log.e(TAG, e.getLocalizedMessage());
    } catch (SAXException e) {
      Log.e(TAG, e.getLocalizedMessage());
    }
    db.close();
    return currentFeed;
  }

}
